﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
using System.DirectoryServices.Protocols;
using System.DirectoryServices;
using System.Text;
using System.Data.SqlClient;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace sccf
{
    public class ConexionLDAP
    {       
        public static List<Usuario> obtenerInfo(string grupo)
        {

            
            List<Usuario> _resultado = new List<Usuario>();     //Lista de usuarios con los datos de los miembros de la Oficina de TI
            List<String> _logins = new List<String>();          //Lista con los logins de los miembros de la Oficina de TI

            //    #region buscar login

            //    //Busca los memberUid del grupo soporte
            int _conta = 0;
            //    // Crear conexion con LDAP
            LdapDirectoryIdentifier serverInfo = new LdapDirectoryIdentifier(Vars.LDAP_SERVER);
            LdapConnection openLdap = new LdapConnection(Vars.LDAP_SERVER);
            openLdap.Credential = new System.Net.NetworkCredential(Vars.LDAP_USER, Vars.LDAP_PASS);
            openLdap.AuthType = AuthType.Basic;
            openLdap.SessionOptions.ProtocolVersion = 3; // Hay que usar LDAPv3
            openLdap.Bind(); //Conectar
            string[] attributesToReturn = new string[] { "memberUid" }; // Atributos a retornar
            SearchRequest searchRequest = new SearchRequest("ou=group,dc=ic-itcr,dc=ac,dc=cr", "cn=" + grupo,
                System.DirectoryServices.Protocols.SearchScope.Subtree);     //Filtro de busqueda.
            SearchResponse searchResponse = (SearchResponse)openLdap.SendRequest(searchRequest); // Respuesta del servidor 
            DirectoryAttribute atributo = searchResponse.Entries[0].Attributes["memberUid"];
            object[] objeto = atributo.GetValues(Type.GetType("System.Byte[]"));

            foreach (object ob in objeto)
            {
                String _login = Encoding.ASCII.GetString((byte[])objeto[_conta]);
                _logins.Add(_login);
                _conta++;
            }
            foreach (String login in _logins)
            {
                try
                {
                    Usuario _usuario = new Usuario();
                    string[] _datos = new string[] { "displayName", "mail", "mailLocalAddress", "userPassword",}; // Atributos a retornar
                    // Buscar al usuario por su login
                    SearchRequest _buqueda = new SearchRequest("ou=people,dc=ic-itcr,dc=ac,dc=cr", "(uid=" + login + "*)",
                        System.DirectoryServices.Protocols.SearchScope.Subtree, _datos);
                    SearchResponse _respuesta = (SearchResponse)openLdap.SendRequest(_buqueda); // Respuesta del servidor
                    
                    DirectoryAttribute _atributo = _respuesta.Entries[0].Attributes["displayName"];
                    object[] _objeto = _atributo.GetValues(Type.GetType("System.Byte[]"));
                    _usuario.Nombre = Encoding.ASCII.GetString((byte[])_objeto[0]);

                    
                    _atributo = _respuesta.Entries[0].Attributes["mail"];
                    _objeto = _atributo.GetValues(Type.GetType("System.Byte[]"));
                    _usuario.Correo = Encoding.ASCII.GetString((byte[])_objeto[0]);

                    _atributo = _respuesta.Entries[0].Attributes["mailLocalAddress"];
                    _objeto = _atributo.GetValues(Type.GetType("System.Byte[]"));
                    _usuario.Correo2 = Encoding.ASCII.GetString((byte[])_objeto[0]);



                    _atributo = _respuesta.Entries[0].Attributes["userPassword"];
                    _objeto = _atributo.GetValues(Type.GetType("System.Byte[]"));
                    _usuario.pass = Encoding.ASCII.GetString((byte[])_objeto[0]);

                    _usuario.login = login;
                    _usuario.cargo = grupo;
                    _resultado.Add(_usuario);
                }
                catch (Exception e)
                {

                }
            }
            openLdap.Dispose(); // Liberar recursos
            return _resultado;
        }
        public static List<string> GetGroups()
        {
            List<String> groups= new List<String>();          //Lista con los logins de los miembros de la Oficina de TI

            //    #region buscar login

            //    //Busca los memberUid del grupo soporte
            int _conta = 0;
            //    // Crear conexion con LDAP
            LdapDirectoryIdentifier serverInfo = new LdapDirectoryIdentifier(Vars.LDAP_SERVER);
            LdapConnection openLdap = new LdapConnection(Vars.LDAP_SERVER);
            openLdap.Credential = new System.Net.NetworkCredential(Vars.LDAP_USER, Vars.LDAP_PASS);
            openLdap.AuthType = AuthType.Basic;
            openLdap.SessionOptions.ProtocolVersion = 3; // Hay que usar LDAPv3
            openLdap.Bind(); //Conectar
            string[] attributesToReturn = new string[] { "cn" }; // Atributos a retornar
            SearchRequest searchRequest = new SearchRequest("ou=group,dc=ic-itcr,dc=ac,dc=cr", "cn=*",
                System.DirectoryServices.Protocols.SearchScope.Subtree);     //Filtro de busqueda.
            SearchResponse searchResponse = (SearchResponse)openLdap.SendRequest(searchRequest); // Respuesta del servidor 
            for (int i = 0; i < searchResponse.Entries.Count; i++)
            {
                DirectoryAttribute atributo = searchResponse.Entries[i].Attributes["cn"];
                object[] objeto = atributo.GetValues(Type.GetType("System.Byte[]"));

                foreach (object ob in objeto)
                {
                    String _login = Encoding.ASCII.GetString((byte[])ob);
                    groups.Add(_login);
                    _conta++;
                }
            }
            openLdap.Dispose(); // Liberar recursos
            return groups;
        }
        public static List<string> GetUsersperGroup(string group)
        {
            int _conta = 0;
            List<string> _logins = new List<string>();
            LdapDirectoryIdentifier serverInfo = new LdapDirectoryIdentifier(Vars.LDAP_SERVER);
            LdapConnection openLdap = new LdapConnection(Vars.LDAP_SERVER);
            openLdap.Credential = new System.Net.NetworkCredential(Vars.LDAP_USER, Vars.LDAP_PASS);
            openLdap.AuthType = AuthType.Basic;
            openLdap.SessionOptions.ProtocolVersion = 3; // Hay que usar LDAPv3
            openLdap.Bind(); //Conectar
            string[] attributesToReturn = new string[] { "memberUid" }; // Atributos a retornar
            SearchRequest searchRequest = new SearchRequest("ou=group,dc=ic-itcr,dc=ac,dc=cr", "cn=" + group,
                System.DirectoryServices.Protocols.SearchScope.Subtree);     //Filtro de busqueda.
            SearchResponse searchResponse = (SearchResponse)openLdap.SendRequest(searchRequest); // Respuesta del servidor 
            DirectoryAttribute atributo = searchResponse.Entries[0].Attributes["memberUid"];
            object[] objeto = atributo.GetValues(Type.GetType("System.Byte[]"));

            foreach (object ob in objeto)
            {
                String _login = Encoding.ASCII.GetString((byte[])objeto[_conta]);
                _logins.Add(_login);
                _conta++;
            }
            return _logins;
        }
        public static string autenticarUsuario(string nombreUsuario, string password)
        {
            // Valida usuario y contraseña correctos
            LdapDirectoryIdentifier serverInfo = new LdapDirectoryIdentifier(Vars.LDAP_SERVER);
            LdapConnection openLdap = new LdapConnection(Vars.LDAP_SERVER);
            openLdap.Credential = new System.Net.NetworkCredential("uid=" + nombreUsuario + ",ou=people,dc=ic-itcr,dc=ac,dc=cr", password);
            openLdap.AuthType = AuthType.Basic;
            openLdap.SessionOptions.ProtocolVersion = 3;
            try
            {
                openLdap.Bind();
                if (GetUsersperGroup("AdminConsejo").Contains(nombreUsuario))
                    return "AdminConsejo";
                else if (GetUsersperGroup("AsistConsejo").Contains(nombreUsuario))
                    return "AsistConsejo";
                else if (GetUsersperGroup("Consejo").Contains(nombreUsuario))
                    return "Consejo";
            }
            catch (Exception e)
            {
                string result = LoginModel.login(nombreUsuario,generarClaveSha(password));
                
                    //login en BD directamente!
                if (result.CompareTo("Administrador") == 0)
                    return "AdminConsejo";
                else if (result.CompareTo("Asistente") == 0)
                    return "AsistConsejo";
                else if (result.CompareTo("Consejo") == 0)
                    return "Consejo";
                else
                    return null;
            }
            return null;
        }
        public static Usuario  buscarUsuario(string clave)
        {


            Usuario user = new Usuario();
            List<String> datos = new List<String>();
            LdapDirectoryIdentifier serverInfo = new LdapDirectoryIdentifier(Vars.LDAP_SERVER);
            LdapConnection openLdap = new LdapConnection(Vars.LDAP_SERVER);
            openLdap.Credential = new System.Net.NetworkCredential(Vars.LDAP_USER, Vars.LDAP_PASS);
            openLdap.AuthType = AuthType.Basic;
            openLdap.SessionOptions.ProtocolVersion = 3; // Hay que usar LDAPv3
            openLdap.Bind(); // Conectar


            string[] attributesToReturn = new string[] { "gecos", "cn", "sn", "homePhone", "mobile", "mail", "description" }; // Retornar solamente el login
            SearchRequest searchRequest = new SearchRequest("ou=people,dc=ic-itcr,dc=ac,dc=cr", "(uid=" + clave + "*)",
                System.DirectoryServices.Protocols.SearchScope.Subtree, attributesToReturn); // Buscar por carnet
            SearchResponse searchResponse = (SearchResponse)openLdap.SendRequest(searchRequest); // Respuesta del servidor
            if (searchResponse.Entries.Count == 0)
                return null;
            //Cambiar a String cada atributo del usuario
            for (int i = 0; i < attributesToReturn.Length; i++)
            {
                DirectoryAttribute atributo = searchResponse.Entries[0].Attributes[attributesToReturn[i]];
                if (atributo != null)
                {
                    object[] objeto = atributo.GetValues(Type.GetType("System.Byte[]"));
                    datos.Add(Encoding.ASCII.GetString((byte[])objeto[0]));
                }
                else
                {
                    datos.Add("Atributo Nulo!");
                }
            }
            user.id = datos.ElementAt(0).Split(' ')[0];			// Carnet
            user.Nombre = datos.ElementAt(1);						// Nombre// Teléfono Celular
            user.Correo = datos.ElementAt(5);						// Correo
            user.cargo = datos.ElementAt(6);						// Descripcion 
            user.login = clave;										// Login

            
            openLdap.Dispose();                        //Liberar recursos	

            return user;

        }
        public static void agregarGrupo(string nombreUsuario, string grupo)
        { // CONSULTAR ESTO ANTES DE PONERLO EN EJECUCIÓN
            LdapDirectoryIdentifier serverInfo = new LdapDirectoryIdentifier(Vars.LDAP_SERVER);
            LdapConnection openLdap = new LdapConnection(Vars.LDAP_SERVER);//Conexion
            openLdap.Credential = new System.Net.NetworkCredential(Vars.LDAP_USER, Vars.LDAP_PASS);
            openLdap.AuthType = AuthType.Basic;
            openLdap.SessionOptions.ProtocolVersion = 3; // Hay que usar LDAPv3
            openLdap.Bind(); // Conectar
            // Agregar el usuario al grupo especificado
            openLdap.SendRequest(new ModifyRequest("cn=" + grupo + ",ou=group,dc=ic-itcr,dc=ac,dc=cr", DirectoryAttributeOperation.Add, "memberUid", nombreUsuario));
            openLdap.Dispose();
        }
        public void cambiarContrasena(string nombreUsuario, string password)
        {
            LdapDirectoryIdentifier serverInfo = new LdapDirectoryIdentifier(Vars.LDAP_SERVER);
            LdapConnection openLdap = new LdapConnection(Vars.LDAP_SERVER);
            openLdap.Credential = new System.Net.NetworkCredential(Vars.LDAP_USER, Vars.LDAP_PASS);
            openLdap.AuthType = AuthType.Basic;
            openLdap.SessionOptions.ProtocolVersion = 3; // Hay que usar LDAPv3
            openLdap.Bind(); // Conectar

            ModifyRequest increment = new ModifyRequest("uid=" + nombreUsuario + ",ou=people,dc=ic-itcr,dc=ac,dc=cr"
                , DirectoryAttributeOperation.Replace, "userPassword", generarClaveSha(password));
            openLdap.SendRequest(increment);
            openLdap.Dispose();
        }
        private static String generarClaveSha(string password)
        {
            SHA1 hasher = SHA1CryptoServiceProvider.Create();
            return "{SHA}" + Convert.ToBase64String(hasher.ComputeHash(Encoding.ASCII.GetBytes(password)));
        }
    }


}